package com.zhq.okhttp.Interceptor;


import android.util.ArrayMap;

import com.alibaba.fastjson.JSON;
import com.zhq.apputil.utils.LogUtil;
import com.zhq.apputil.utils.StringUtil;
import com.zhq.constant.AppConstant;
import com.zhq.okhttp.ApiServer;
import com.zhq.okhttp.bean.HttpBeanResponse;

import java.io.EOFException;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.UnsupportedCharsetException;

import okhttp3.Headers;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okio.Buffer;
import okio.BufferedSource;
import retrofit2.Call;

/***
 * token拦截器
 */
public class TokenInterceptor implements Interceptor {
    private static final Charset UTF8 = Charset.forName("UTF-8");

    private boolean bodyEncoded(Headers headers) {
        String contentEncoding = headers.get("Content-Encoding");
        return contentEncoding != null && !contentEncoding.equalsIgnoreCase("identity");
    }

    static boolean isPlaintext(Buffer buffer) {
        try {
            Buffer prefix = new Buffer();
            long byteCount = buffer.size() < 64 ? buffer.size() : 64;
            buffer.copyTo(prefix, 0, byteCount);
            for (int i = 0; i < 16; i++) {
                if (prefix.exhausted()) {
                    break;
                }
                int codePoint = prefix.readUtf8CodePoint();
                if (Character.isISOControl(codePoint) && !Character.isWhitespace(codePoint)) {
                    return false;
                }
            }
            return true;
        } catch (EOFException e) {
            return false; // Truncated UTF-8 sequence.
        }
    }

    @Override
    public Response intercept(Chain chain) throws IOException {
        Response response = chain.proceed(getNewRequest(chain));
        ResponseBody responseBody = response.body();
        long contentLength = responseBody.contentLength();
        if (!bodyEncoded(response.headers())) {
            BufferedSource source = responseBody.source();
            source.request(Long.MAX_VALUE); // Buffer the entire body.
            Buffer buffer = source.buffer();
            Charset charset = UTF8;
            MediaType contentType = responseBody.contentType();
            if (contentType != null) {
                try {
                    charset = contentType.charset(UTF8);
                } catch (UnsupportedCharsetException e) {
                    return response;
                }
            }

            if (!isPlaintext(buffer)) {
                return response;
            }
            if (contentLength != 0) {
                String result = buffer.clone().readString(charset);
                LogUtil.e(" response.url():" + response.request().url());
                LogUtil.e(" response.body():" + result);
                //得到所需的string，开始判断是否异常
                if (isTokenExpired(result)) {//根据和服务端的约定判断token过期
                    //同步请求方式，获取最新的Token
                    String newSession = getNewToken();
                    if (!StringUtil.isEmpty(newSession)) {
                        Request newRequest = chain.request()
                                .newBuilder()
                                .addHeader("token","")
                                .build();
                        //重新请求
                        return chain.proceed(newRequest);
                    } else {
                        return response;
                    }
                }
            }
        }
        return response;
    }

    /***
     * 添加新的Request，获取登录token放进头部
     * @param chain
     * @return
     */
    private Request getNewRequest(Chain chain) {
        Request newRequest = chain.request()
                .newBuilder()
                .addHeader("token", "")
                .build();
        return newRequest;
    }

    /**
     * 根据Response，判断Token是否失效 * * @param response * @return
     */
    private boolean isTokenExpired(String data) {
        try {
            HttpBeanResponse beanResponse = JSON.parseObject(data, HttpBeanResponse.class);
            if (beanResponse.getStatusCode() == AppConstant.HttpResponse.TOKEN_EXPIRED) {
                LogUtil.e("TokenInterceptor", "current session token is invalid");
                return true;
            }
        } catch (Exception e) {//解析异常以及IO异常
            return false;
        }
        return false;
    }

    /**
     * 同步请求获取新的markCode
     **/
    public synchronized String getNewToken() {
        String markCode = "";
        //LoginSharePresenter.getInstance().getMarkCodeBean().getMarkCode();
        if (!StringUtil.isEmpty(markCode)) {
            try {
                ArrayMap<String, String> map = new ArrayMap<>();
                map.put("markCode", markCode);
                Call<ResponseBody> responseBody = ApiServer.getNetService().getRefreshToken(map);
                String data = responseBody.execute().body().string();
                HttpBeanResponse beanResponse = JSON.parseObject(data, HttpBeanResponse.class);
                if (beanResponse.getStatusCode() == AppConstant.HttpResponse.SUCCESS) {//自动登录成功
                    LogUtil.e("TokenInterceptor", "current session token is success");
                    return markCode;
                } else {
                    return "";
                }
            } catch (IOException e) {
                e.printStackTrace();
                LogUtil.e("IOException：" + e.getMessage());
            }

        }
        return markCode;
    }
}
